#pragma once

#include <math.h>
#include <string.h>

#include "hs_math.h"

#define Class Mod2
#define Type Mod2<Ring>
#include "hs_vector2_body.h"
#undef Class
#undef Type

#define Class Vec2
#define Type Vec2<Ring>
#define VECTOR
#define ModClass Mod2
#include "hs_vector2_body.h"
#undef Class
#undef Type
#undef VECTOR
#undef ModClass

#define Class Mod3
#define Type Mod3<Ring>
#include "hs_vector3_body.h"
#undef Class
#undef Type

#define Class Vec3
#define Type Vec3<Ring>
#define VECTOR
#define ModClass Mod3
#include "hs_vector3_body.h"
#undef Class
#undef Type
#undef VECTOR
#undef ModClass

#define Class Mod4
#define Type Mod4<Ring>
#include "hs_vector4_body.h"
#undef Class
#undef Type

#define Class Vec4
#define Type Vec4<Ring>
#define VECTOR
#define ModClass Mod4
#include "hs_vector4_body.h"
#undef Class
#undef Type
#undef VECTOR
#undef ModClass

template<class Ring, class Field>
Mod2<Ring> Floor(const Vec2<Field>& v) {
  return Mod2<Ring>(floor(v.X), floor(v.Y));
}

template<class Ring, class Field>
Mod3<Ring> Floor(const Vec3<Field>& v) {
  return Mod3<Ring>(floor(v.X), floor(v.Y), floor(v.Z));
}

template<class Ring, class Field>
Mod4<Ring> Floor(const Vec4<Field>& v) {
  return Mod4<Ring>(floor(v.X), floor(v.Y), floor(v.Z), floor(v.W));
}

typedef Mod2<int> Mod2i;
typedef Mod3<int> Mod3i;
typedef Mod4<int> Mod4i;
typedef Vec2<float> Vec2f;
typedef Vec3<float> Vec3f;
typedef Vec4<float> Vec4f;
typedef Vec2<double> Vec2d;
typedef Vec3<double> Vec3d;
typedef Vec4<double> Vec4d;
